import turbogears
import turbogears.widgets as widgets

import mnemoply._renewed_lib.validators as validators
from mnemoply._renewed_utils import find_class, get_by_key_and_delete, get_user_office
import mnemoply._renewed_model.field as field
from mnemoply._renewed_constants import getDefaultController
from mnemoply.common_knowledge import actual_years, day_captions, month_captions


import mnemoply.model as old_model

Label = widgets.Label
URLLink = widgets.URLLink
TextField = widgets.TextField
Widget = widgets.Widget
HiddenField = widgets.HiddenField
TextArea = widgets.TextArea
CheckBox = widgets.CheckBox
Button = widgets.Button


class CalendarDatePicker  (widgets.CalendarDatePicker):
    button_text = _("Calendar")
    format="%d.%m.%Y"

    def __init__(self,*args,**kw):
        widgets.CalendarDatePicker.__init__(self,*args,**kw)
        self.validator = validators.tg_validators.DateTimeConverter(format="%d.%m.%Y")

class FKeyLink(widgets.URLLink):
    """
        Create link to foreign key instance.
    """ 
    def __init__(self, fkey_class, obj_id, obj_title, *args, **kw):
        URLLink.__init__(self, *args, **kw)
        controller = getDefaultController(fkey_class)
        self.link = '/%s/%s'% (controller,obj_id)
        self.text =  obj_title
    
class TextReadOnly(TextField):
    attrs={'readonly':True, 'style':'border:None;', }
    css_class='font-black'
    

class TextAreaReadOnly(TextArea):
    attrs={'readonly':True, 'style':'border:None;', 'rows':0, 'cols':20 }
    css_class='font-black'

class TableForm(widgets.TableForm):
    params = ['title', 'btn_attrs']
    title = ''
    btn_attrs = {}
    template = "mnemoply._renewed_templates.table"

class GridForm(TableForm):
    params = ['column_headers','row_count','col_count']
    row_count=0
    col_count=0
    column_headers = []
    template = "mnemoply._renewed_templates.table_grid"
    

class ImageLink(URLLink):
    params = ['img_src','img_attrs']
    img_src=''
    template = """
    <a xmlns:py="http://purl.org/kid/ns#"
       href="$link"
       target="$target"
       py:attrs="attrs"
    ><img src='$img_src'  alt='$text' title = '$text' py:attrs="img_attrs" /></a>
    """
    img_attrs = dict(width=22, height = 22)
    def __init__(self,  *args,**kw):
        URLLink.__init__(self, *args,**kw)
        self.text = kw.get('text') or self.text
        self.img_src =kw.get('img_src') or self.img_src
        self.link = kw.get('link') or self.link
        new_attr = kw.get('img_attrs', self.img_attrs)
        self.img_attrs = dict( self.img_attrs, **new_attr)

class ImageLinkDelete(ImageLink):
    img_src='/static/images/trash.png'
    text = _("Delete")
    link = 'delete'
    attrs = dict(onclick="return confirm('%s')"% _("Are you sure you want to delete this?"))
    
class ImageLinkEdit(ImageLink):
    img_src='/static/images/edit.png'
    text= _("Edit")
    link = 'edit_req'

class ImageLinkList(ImageLink):
    img_src='/static/images/table.gif'
    text= _("List")
    link = '../list'

class ImageLinkListAdd(ImageLink):
    img_src='/static/images/table.gif'
    text= _("List")
    link = 'list'
    
class ImageLinkAdd(ImageLink):
    img_src='/static/images/add.png'
    text = _("Add")
    link = 'add_req'

class ImageLinkBack(ImageLink):
    img_src='/static/images/up.gif'
    text= _("Back")
    link = 'javascript:history.back()'

class ImageLinkShow(ImageLink):
    img_src='/static/images/icon_eye.gif'
    text = _("View")
    link = 'show'



class AutoCompleteField(widgets.AutoCompleteField):
    """
        Base class for autocomplete field.
    """
    # Unsupported param, provided here to remove warnings
    params = ["not_empty", "has_add_btn", "has_info_btn", "controller_name","info_func"]
    not_empty = True
    controller_name = ""
    info_func = ""
    search_controller = ''
    has_add_btn = True
    has_info_btn = True
    hidden_field = HiddenField(name="hidden",)
                           #    attrs=dict()   

    template = """
<div xmlns:py="http://purl.org/kid/ns#">
    <script language="JavaScript" type="text/JavaScript">
        AutoCompleteManager${field_id} = new AutoCompleteManager('${field_id}',
        '${text_field.field_id}', '${hidden_field.field_id}',
        '${search_controller}', '${search_param}', '${result_name}',${str(only_suggest).lower()},
        '${tg.url([tg.widgets, 'turbogears.widgets/spinner.gif'])}', ${complete_delay}, ${str(take_focus).lower()});
        addLoadEvent(AutoCompleteManager${field_id}.initialize);
    </script>

    ${text_field.display(value_for(text_field), **params_for(text_field))}
    <input py:if="has_add_btn" type = 'button' value = '+'
                   onclick = 'openFrame("/${controller_name}/add_req","ifr");'/>
    <input py:if="has_info_btn" type = 'button' value = 'e'
                   onclick = 'openInfo("${controller_name}","form_${name}_hidden", "/edit_req");'/>
    <img name="autoCompleteSpinner${name}" id="autoCompleteSpinner${field_id}"
    src="${tg.url([tg.widgets, 'turbogears.widgets/spinnerstopped.png'])}" alt="" />
    <div class="autoTextResults" id="autoCompleteResults${field_id}"/>
    ${hidden_field.display(value_for(hidden_field), **params_for(hidden_field))}
 
</div>
    """
    #<input py:if="has_info_btn" type = 'button' value = 'i'
    #               onclick = 'openInfo("${controller_name}","form_${name}_hidden", "/show");'/>

    def __init__(self, model_object_name, *args, **kw):

        super(AutoCompleteField, self).__init__(*args, **kw)
        self.controller_name = self.controller_name \
                               or getDefaultController(model_object_name)
        search_controller = self.search_controller or 'find'
        if '/' in search_controller:
            self.search_controller = search_controller
        else:
            self.search_controller = "/%s/%s" % (self.controller_name,
                                                 search_controller)
        info_func = self.info_func or 'get_info'
        if '/' in info_func:
            self.info_func = info_func
        else:
            self.info_func = "/%s/%s" %( self.controller_name,info_func)

        self.validator = validators.AutoCompleteSchema()
        model_object = find_class(model_object_name)
        val = validators.AutoCompleteFieldValidator(model_object = model_object)
        self.validator.add_chained_validator(val)
        val = validators.formencode_validators.Int(not_empty=self.not_empty)
        self.validator.add_chained_validator(val)

    def adjust_value(self, value, **kw):
        if isinstance(value, dict):
            return value
        return self.validator.from_python(value)


class StudentField(AutoCompleteField):
    """
        Autocomplete field for Student model object.
    """
    search_controller = "/Personality_new/find"
    controller_name = "Student_new"
    def __init__(self, *args, **kw):
        AutoCompleteField.__init__(self, model_object_name='StudentNew',*args, **kw)

class GroupField(AutoCompleteField):
    def __init__(self, *args, **kw):
        AutoCompleteField.__init__(self, model_object_name='Group',*args, **kw)

class BackWidget(widgets.Widget):
    """
        Create back link from history.
    """

    params = ['method', 'dont_center']

    _("Back")

    template = """
        <div xmlns:py="http://purl.org/kid/ns#" id="back-widget"
            py:attrs="dont_center and {} or dict(align='center')">
             <a py:attrs="href=href">Back</a> 
        </div>
    """

    # Correct values: back-button and referer
    method = 'back-button'
    dont_center = False

    def update_params(self, d):
        super(BackWidget, self).update_params(d)

        method = d['method']
        assert method in ['back-button', 'referer']

        if method == 'back-button':
            href = 'javascript:history.back()'
        else:
            assert method == 'referer'
            href = cherrypy.request.headerMap.get('Referer', 'javascript:history.back()')
        d['href'] = href

def add_back_widget(vars, back_widget=BackWidget()):
    vars['back_widget'] = back_widget
turbogears.view.variable_providers.append(add_back_widget)


class TextWithHelperField(widgets.FormField):
    """A standard, single-line text field with drop-down helper."""

    template = """
    <span xmlns:py="http://purl.org/kid/ns#">

    <input type="text"
        name="${name}"
        class="${field_class}"
        id="${field_id}"
        value="${value}"
        py:attrs="attrs"
    />

    <select class="${field_class}"
            onchange="document.getElementById('${field_id}').value = this.value; this.value = ''"
    >
        <option py:for="value, desc in options"
            value="${value}"
            py:content="desc"
        />
    </select>

    </span>
    """

    params = ["attrs", "records"]
    params_doc = {'attrs': 'Dictionary containing extra (X)HTML attributes for the input tag'}
    attrs = {}

    def get_options(self, records):
        result = [('', '')]
        if len(records)<=0:
            return result
        if isinstance(records[0],tuple):
            result+=[(x[0], x[1]) for x in records]
        else:
            result += [(x, x) for x in records]
        return result

    def display(self, *args, **kw):
        records = kw.get('records', self.records)
        if callable(records):
            records = records()
        kw['options'] = self.get_options(records)
        return super(widgets.FormField, self).display(*args, **kw)


class PhoneMainField(widgets.CompoundFormField):
    params = ['num', 'code']
    num = code = None

    template = """
    <table xmlns:py="http://purl.org/kid/ns#"
        width = "100%" aling="left" border="0"
        
        cellspacing ='0' cellpadding ='0'>
        <tr>
            <td>Code</td>
            <td>
                    <span py:replace="fields[0].display(value_for(fields[0]), **params_for(fields[0]))" />
            </td>
            <td rowspan='2'>
                <textarea form="" name='result_check_phone' rows='2'
                        style="border:0; width:100%;margin:0;padding:0;"
                        id='result_check_phone' readonly='true'>
                </textarea>
            </td>
        </tr>
        <tr>
            <td>Number </td>
            <td>${fields[1].display(value_for(fields[1]), **params_for(fields[1]))}</td>
        </tr>
        <tr>
            <td colspan='2'>
                <input type = 'Button'
                    value = "${_('Check')}"
                    onclick='remoteRequestForError(this.form,"phone_main","check_phone")'/>
            </td>
         </tr>
    </table>    
    """
    
    def __init__(self, not_empty=False, *args, **kw):
        num = TextField(name='num',field_class = 'textfield_middle',)
        code = TextWithHelperField(name='code',
                                   field_class = 'textfield_small',
                        records = [(x.value,x.name ) for x in old_model.PhoneCode.select() ]
                        )
        self.code = code
        
        validator = validators.PhoneMainSchema()
        v = get_by_key_and_delete('validator',kw)
        if v and v != validator:
            validator.chained_validators.append(v)
        
        super(PhoneMainField, self).__init__( fields = [code, num],
                                         validator = validator,
                                         *args, **kw)

    def adjust_value(self, value, **kw):
        print 'phone ', value
        print kw
        return self.validator.from_python(value)

class DictionaryField( widgets. SingleSelectField):
    sort_func  =  lambda self, x: x.title
    sort_reverse = False
    filter_func = lambda self,x: True
    caption_func = lambda self,x: (x.id, x.title, dict(aa='1', bb = '2'))
    not_empty = False
    empty_caption = '' 

    def make_list(self,select, need_sort = True):
        def _call():
            lst = list(select)
            ff = self.filter_func
            lst =[a for a in lst  if ff(a)]
            if need_sort:  #TODO
                lst.sort(key= self.sort_func, reverse = self.sort_reverse)
            res = [self.caption_func(a) for a in lst  ]
            if not self.not_empty:
                res = [('',self.empty_caption)]+res
            return res
        return _call
    
    def __init__(self, select,*args,**kw):
        self.sort_func  =  get_by_key_and_delete('sort_func',kw,self.sort_func)
        self.sort_reverse = get_by_key_and_delete('sort_reverse',kw,self.sort_reverse)
        self.filter_func = get_by_key_and_delete('filter_func',kw,self.filter_func)
        self.caption_func = get_by_key_and_delete('caption_func',kw,self.caption_func)
        self.not_empty = get_by_key_and_delete('not_empty',kw,self.not_empty)
        options = self.make_list(select)
        widgets. SingleSelectField.__init__(self,options = options,
                                                validator = validators.tg_validators.Int(),
                                                *args, **kw)
def getFreeAccount(**params) :
    return DictionaryField(
        select = field.AccountFree.select(),
        filter_func= lambda r:r.is_free and \
                     (r.office== get_user_office() if get_user_office() else True),
        **params
        )

class DataGridWidget(widgets.DataGrid, widgets.FormFieldsContainer):
    params = ['name','is_can_set_shown','hidden_fields']
    name = ''
    is_can_set_shown = {}
    hidden_fields = []
    template = "mnemoply._renewed_templates.grid"



class ApplyToAllWidget(widgets.CompoundFormField):
    template = """<div xmlns:py="http://purl.org/kid/ns#">
            <span py:if ="len(fields)>0" py:replace="fields[0].display(value_for(fields[0]), **params_for(fields[0]))" />
            <span py:if ="len(fields)>0" py:replace="fields[1].display(value_for(fields[1]), **params_for(fields[1]))" />
        </div>"""
    widget = widgets.Label
    def __init__(self, name, widget, *args, **kw):
        self.widget = widget
        self.name = "apply"
        func = self.define_func()
        fields = []
        if 'attrs' in kw and ('readonly' in kw['attrs']  or 'disabled' in kw['attrs']  ):
            func=''
        if func:
            func = "%s('%s');"%(func,name)
            fields =[
                    widget(
                            name=name,
                            **kw
                            ),
                    widgets.Button(
                            default = _('Apply to all'),
                            attrs = {'onclick': func}
                            )
                    ]
        
        super(ApplyToAllWidget, self).__init__(fields=fields)
    def define_func(self):
        default = [CalendarDatePicker,TextArea,TextField,widgets.SingleSelectField]
        autoComplete = [AutoCompleteField]
        checkFox =[widgets.CheckBox]
        func = dict(default="setAllDefault",
                    autoComplete="setAllAutoCompleteField",
                    checkFox="setAllCheckbox",
                    empty="")
        if self.is_subclass_of_any(default):
            return func['default']
        elif self.is_subclass_of_any(autoComplete):
            return func['autoComplete']
        elif self.is_subclass_of_any(checkFox):
            return func['checkFox']
        else:
            return func['empty']

    def is_subclass_of_any(self, lst):       
        for widget in lst:
            if issubclass(self.widget, widget):
                return True
        return False


class PreferedDayField(widgets.CompoundFormField):

    template = """
        <table border="0" cellspacing="0" cellpadding="2" xmlns:py="http://purl.org/kid/ns#">
            <tr py:for="i, field in enumerate(fields)"
                class="${i%2 and 'odd' or 'even'}"
            >
                <th>
                    <label class="fieldlabel" for="${field.field_id}" py:content="field.label" />
                </th>
                <td>
                    <span py:replace="field.display(value_for(field), **params_for(field))" />
                    <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" />
                    <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" />
                </td>
            </tr>
        </table>
    """

    def __init__(self, not_empty=False, *args, **kw):
        field_validator = validators.Bool()

        fields = [
            widgets.CheckBox(str(x), validator=field_validator, label=day_captions[x])
                for x in range(1, 8)
        ]

        self.validator = validators.PreferedDaySchema()
        val = validators.PreferedDayFieldValidator()
        self.validator.add_chained_validator(val)
        super(PreferedDayField, self).__init__(fields=fields, *args, **kw)

    def adjust_value(self, value, **kw):
        if isinstance(value, dict):
            return value
        return self.validator.from_python(value)
